﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using Sharp.Portal.Interface;
using Sharp.Portal.Other;

namespace Sharp.Portal.Mvc.Form
{

    public abstract partial class SharpFrom
    {
        private readonly DataType[] _textType =
        {
            DataType.Text, DataType.MultilineText, DataType.CreditCard, DataType.Currency, DataType.Date,
            DataType.DateTime, DataType.EmailAddress, DataType.Html
        };

        public SharpFrom(object model)
        {
            Model = model;

            Sections = new List<FormSection>();


            PostAction = "Save";
            GoBackAction = "Index";

            Load();
        }

        #region 操作页基本名称

        /// <summary>
        /// 操作页基本名称
        /// </summary>
        public string Title { get; set; }

        private void InitTitle()
        {
            if (HideTitle)
            {
                Title = "";
                return;
            }
            if (Title.IsNullOrEmpty())
            {
                var titleAttribute =
                    this.Model.GetType().GetCustomAttributes(typeof(TitleAttribute), true).FirstOrDefault() as
                        TitleAttribute;
                if (titleAttribute == null)
                {
                    Title = string.Empty;
                }
                else
                {
                    Title = titleAttribute.Title ?? string.Empty;
                }
            }

        }
        #endregion

        /// <summary>
        /// 隐藏标题
        /// </summary>
        public bool HideTitle { get; set; }

        /// <summary>
        /// 宽度
        /// </summary>
        public int Width { get; set; }
        /// <summary>
        /// 高度
        /// </summary>
        public int? Height { get; set; }

        /// <summary>
        /// 打开方式
        /// </summary>
        public OpenWith OpenWith { get; set; }

        /// <summary>
        /// 章节
        /// </summary>
        public IList<FormSection> Sections { get; set; }

        /// <summary>
        /// 表单ViewModel
        /// </summary>
        public object Model { get; set; }

        /// <summary>
        /// post表单的地址
        /// </summary>
        public string PostAction { get; set; }
        /// <summary>
        /// 返回的地址
        /// </summary>
        public string GoBackAction { get; set; }

        #region 初始化表单

        /// <summary>
        /// 初始化表单
        /// </summary>
        protected virtual void InitForm()
        {
            Type modelType = this.Model.GetType();
            InitForm(modelType, null, string.Empty);


            if (this.FieldsHandle != null)
            {
                FieldsHandle.Invoke(this.Sections);
            }
        }
        /// <summary>
        /// 初始化表单
        /// </summary>
        /// <param name="modelType"></param>
        /// <param name="sectionAttribute"></param>
        /// <param name="path"></param>
        private void InitForm(Type modelType, SectionAttribute sectionAttribute, string path)
        {
            if (sectionAttribute == null)
            {
                sectionAttribute = modelType.GetCustomAttributes(typeof(SectionAttribute))
                    .FirstOrDefault() as SectionAttribute;
            }

            if (sectionAttribute == null)
            {
                sectionAttribute = new SectionAttribute("基本");
            }


            var sectionTitle = sectionAttribute.Title;


            var section = new FormSection(sectionTitle);
            section.Path = path;
            section.ItemsFromAction = sectionAttribute.ItemsFromAction;
            section.RouteValues = sectionAttribute.RouteValues;
            this.Sections.Add(section);

            foreach (var property in modelType.GetProperties())
            {
                var customAttributes = property.GetCustomAttributes().ToArray();
                if (customAttributes.Any(x => x is SectionAttribute))
                {
                    var sa = customAttributes.First(x => x is SectionAttribute) as SectionAttribute;

                    InitForm(property.PropertyType, sa, property.Name);
                }
                if (!customAttributes.Any(x => x is HiddenInputAttribute || x is DisplayAttribute))
                {
                    FindAllHiddenInput(section.Fields, property);
                    continue;
                }

                var fieldItem = new FieldItem();
                fieldItem.ParentForm = this;
                fieldItem.PropertyType = property.PropertyType;
                if (section.Path.Length > 0)
                    fieldItem.Name = section.Path + "." + property.Name;
                else
                    fieldItem.Name = property.Name;

                if (customAttributes.FirstOrDefault(x => x is HiddenInputAttribute) is HiddenInputAttribute)
                {
                    fieldItem.FieldType = FieldType.HiddenInput;
                    section.Fields.Add(fieldItem);

                    continue; //隐藏域控件到此。
                }

                var customAttribute = customAttributes.FirstOrDefault(x => x is DisplayAttribute) as DisplayAttribute;
                if (customAttribute == null)
                {
                    continue;
                }


                fieldItem.FieldLabel = customAttribute.Name;
                fieldItem.Order = customAttribute.GetOrder() ?? int.MaxValue;
                fieldItem.Prompt = customAttribute.Prompt;
                fieldItem.Description = customAttribute.Description;

                var dataType =
                    property.GetCustomAttributes(typeof(DataTypeAttribute), false)
                        .FirstOrDefault() as DataTypeAttribute;
                if (dataType == null && property.PropertyType == typeof(string))
                {
                    fieldItem.DataType = DataType.Text;
                }
                else
                {
                    if (dataType != null)
                    {
                        fieldItem.DataType = dataType.DataType;
                    }
                }

                #region FieldType 赋值

                if (_textType.Any(x => x == fieldItem.DataType))
                {
                    fieldItem.FieldType = FieldType.TextBox;
                }


                if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?))
                {
                    fieldItem.FieldType = FieldType.Boolean;
                }
                #endregion

                if (property.GetCustomAttributes(typeof(MasterDataAttribute), false)
                    .FirstOrDefault() is MasterDataAttribute masterData)
                {
                    fieldItem.FieldType = FieldType.MasterData;
                    fieldItem.MasterDataCategory = masterData.Category;
                }
                if (property.GetCustomAttributes(typeof(CustomFieldAttribute), false)
                    .FirstOrDefault() is CustomFieldAttribute customField)
                {
                    fieldItem.FieldType = customField.FieldType;
                    fieldItem.DisplayField = customField.DisplayField;
                    fieldItem.ValueField = customField.ValueField;

                    fieldItem.DataSourceName = customField.DataSourceName;

                    if (
                        (customField.FieldType == FieldType.OrgTreeList ||
                        customField.FieldType == FieldType.DropDownList ||
                        customField.FieldType == FieldType.TreeList)

                        && customField.DataSourceName.IsNullOrEmpty())
                    {
                        fieldItem.DataSourceName = fieldItem.Name + "DataSource";
                        //#if DEBUG
                        //                        if (modelType.GetProperties().Count(x => x.Name == fieldItem.DataSourceName) == 0)
                        //                        {
                        //                            throw new NotImplementedException("DataSourceName 不存在，请检查是否写错。");
                        //                        }
                        //#endif
                    }

                    if (customField.DataSourceName.IsNotNullOrEmpty()
                        && fieldItem.Name.Contains(".") && !customField.DataSourceName.Contains("."))
                    {
                        fieldItem.DataSourceName = fieldItem.Name.Split('.')[0] + "." + customField.DataSourceName;
                    }


                    if (customField.FieldType == FieldType.SelectBox)
                    {
                        fieldItem.Model = customField.Model;
                    }
                }


                section.Fields.Add(fieldItem);
            }

            section.Fields = section.Fields.OrderBy(x => x.Order).ToList();
        }

        private void FindAllHiddenInput(IList<FieldItem> sectionFields, PropertyInfo property)
        {
            //暂时解决c属性没有自动加入隐藏域控件
            if (property.Name == "UI")
            {
                var fieldItem = new FieldItem();
                fieldItem.ParentForm = this;
                fieldItem.PropertyType = property.PropertyType;
                fieldItem.FieldType = FieldType.HiddenInput;

                fieldItem.Name = "UI.RefreshGrid";
                sectionFields.Add(fieldItem);
            }
        }

        #endregion

        #region 初始化特性标注的属性

        /// <summary>
        /// 初始化特性标注的属性
        /// </summary>
        private void InitPro()
        {
            if (HttpContext.Current.Request.Params["cmd"] == "ItemPanel")
            {
                this.OpenWith = OpenWith.Tile;
            }
            if (this.OpenWith != OpenWith.None)
            {
                return;
            }
            if (!(Model.GetType().GetCustomAttributes(typeof(ItemPageAttribute)).FirstOrDefault() is ItemPageAttribute
                itemPageAttribute))
            {
                if (this.OpenWith == OpenWith.None)
                {
                    this.OpenWith = OpenWith.Window2Column;
                }
            }
            else
            {
                this.Width = itemPageAttribute.Width;

                this.OpenWith = itemPageAttribute.OpenWith;
            }
            if (this.Width.IsEmpty())
                this.Width = 1000;
        }

        #endregion

        /// <summary>
        /// 加载模型时必须执行，无论模板是否已经生成
        /// </summary>
        private void Load()
        {
            InitPro();

            InitTitle();

            Maximizable = true;
            Collapsible = true;
            Resizable = true;
        }

        /// <summary>
        /// 完成初始化，用于模板生成
        /// </summary>
        public void InitComplete()
        {

            CheckReadOnlyForm();

            InitProvider();

            InitForm();
        }

        /// <summary>
        /// 是否只读表单
        /// </summary>
        /// <returns></returns>
        public bool CheckReadOnlyForm()
        {
            var current = HttpContext.Current;

            if (this.IsReadOnlyForm == null)
            {
                bool.TryParse(current.Request.Params["IsReadOnlyForm"], out var isReadOnlyForm);
                this.IsReadOnlyForm = isReadOnlyForm;
            }
            else
            {
                current.Request.RequestContext.RouteData.DataTokens["IsReadOnlyForm"] = this.IsReadOnlyForm.ToString().ToLower();
            }

            return IsReadOnlyForm.Value;
        }

        /// <summary>
        /// 是否只读表单
        /// </summary>
        public bool? IsReadOnlyForm { get; set; }

        public bool Maximizable { get; set; }
        public bool Collapsible { get; set; }
        public bool Resizable { get; set; }
        public bool Maximized { get; set; }
        public LayoutInfo Layout { get; set; }
        /// <summary>
        /// 刷新本表单数据的Url
        /// </summary>
        public string RefreshUrl { get; set; }
        /// <summary>
        /// 隐藏工具栏按钮
        /// </summary>
        public bool HiddenToolButtons { get; set; }
        /// <summary>
        /// 刷新grid的Id
        /// </summary>
        [HiddenInput]
        public string RefreshGrid { get; set; }
        /// <summary>
        /// 适配器
        /// </summary>
        public ITemplateProvider Provider { get; set; }
        /// <summary>
        /// 初始化适配器
        /// </summary>
        public virtual void InitProvider()
        {
            
        }

        public ITemplateProvider GetProvider()
        {
            InitProvider();

            return Provider;
        }
        public class LayoutInfo
        {
            /// <summary>
            /// layout页的路径
            /// </summary>
            public string LayoutPath { get; set; }
            /// <summary>
            /// Section的名称
            /// </summary>
            public string SectionName { get; set; }
        }
    }
}